package org.aiesec.fortaleza.xmatch.model.util;

import java.util.HashMap;
import java.util.Map;

public class Criteria {

	private final String namedQuery;
	private StringBuffer whereQuery;
	private Map<String, Object> parameters = new HashMap<String, Object>();
	@SuppressWarnings("unchecked")
	private final Class clazz;

	private boolean cacheable;

	public Map<String, Object> getParameters() {
		return parameters;
	}

	public String getWhereString() {
		String queryValue = ReflectionUtil.getQueryString(namedQuery, clazz);
		return whereQuery == null ? queryValue : queryValue + " where "
				+ whereQuery.toString();
	}

	@SuppressWarnings("unchecked")
	public Criteria(String namedQuery, Class clazz) {
		this.namedQuery = namedQuery;
		this.clazz = clazz;
	}

	public String getNamedQuery() {
		return namedQuery;
	}

	@SuppressWarnings("unchecked")
	public static Criteria getInstance(String namedQuery, Class clazz) {
		return new Criteria(namedQuery, clazz);
	}

	private void addWhere(String condition, String conditionType) {
		if (whereQuery == null) {
			whereQuery = new StringBuffer();
			whereQuery.append(condition);
		} else {
			whereQuery.append(" " + conditionType + " " + condition);
		}
	}

	public Criteria addAnd(SimpleExpression simpleExpression) {
		add(simpleExpression, "and");
		return this;
	}

	public Criteria addOr(SimpleExpression simpleExpression) {
		add(simpleExpression, "or");
		return this;
	}

	private void add(SimpleExpression simpleExpression, String conditionType) {
		if (simpleExpression.isAvaible()) {
			String scrapQuery = simpleExpression.getScrapQuery("param"
					+ (parameters.size() + 1));
			addWhere(scrapQuery, conditionType);
			parameters.put("param" + Integer.toString(parameters.size() + 1),
					simpleExpression.getValue());
		}
	}

	public Criteria setCacheable(boolean cacheable) {
		this.cacheable = cacheable;
		return this;
	}

	public boolean isCacheable() {
		return cacheable;
	}

}
